<template>
	<div class="chat-container">
		<header class="chat-header">
			<h1>AI智能助手</h1>
		</header>
		<div class="messages-container" ref="messagesContainer">
			<div v-for="(message, index) in messages" :key="index" :class="['message', message.type]">
				<div class="message-content">
					<div v-if="message.type === 'ai'" class="markdown-content"
						v-html="message.htmlContent || message.content"></div>
					<p v-else>{{ message.content }}</p>
				</div>
			</div>
			<div v-if="loading" class="loading-indicator">
				<span v-for="i in 3" :key="i"></span>
			</div>
		</div>
		<div class="input-container">
			<textarea v-model="userInput" placeholder="请输入您的问题..." rows="1" @input="adjustTextareaHeight"
				@keydown="handleKeydown"></textarea>
			<button class="send-button" @click="sendMessage" :disabled="!userInput.trim() || loading">
				<svg viewBox="0 0 24 24" width="24" height="24">
					<path fill="currentColor" d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path>
				</svg>
			</button>
		</div>
	</div>
</template>

<script>
	import {
		marked
	} from 'marked';
	import {
		setToken,
		getToken,
	} from '@/ulm/utils/auth';
	export default {
		name: 'AIChat',
		data() {
			return {
				messages: [{
					type: 'system',
					content: '你好！我是AI助手，有什么可以帮助你的吗？'
				}],
				userInput: '',
				loading: false,
				controller: null
			};
		},
		mounted() {
			this.adjustTextareaHeight();
		},
		methods: {
			adjustTextareaHeight() {
				const textarea = this.$el.querySelector('textarea');
				if (textarea) {
					textarea.style.height = 'auto';
					textarea.style.height = (textarea.scrollHeight > 100 ? 100 : textarea.scrollHeight) + 'px';
				}
			},

			handleKeydown(event) {
				if (event.key === 'Enter' && !event.shiftKey) {
					event.preventDefault();
					this.sendMessage();
				}
			},

			async sendMessage() {
				const message = this.userInput.trim();
				if (!message || this.loading) return;

				// 添加用户消息
				this.messages.push({
					type: 'user',
					content: message
				});

				// 清空输入框
				this.userInput = '';
				this.adjustTextareaHeight();

				// 显示加载状态
				this.loading = true;

				try {
					// 添加AI回复占位消息
					const aiMessageIndex = this.messages.length;
					this.messages.push({
						type: 'ai',
						content: '',
						htmlContent: '',
						isStreaming: true
					});

					// 调用AI接口
					await this.fetchAIResponse(message, aiMessageIndex);
				} catch (error) {
					// 添加错误消息
					this.messages.push({
						type: 'system',
						content: '网络错误，请稍后再试'
					});
					console.error('Error:', error);
				} finally {
					this.loading = false;
					this.$nextTick(() => {
						this.scrollToBottom();
					});
				}
			},

			async fetchAIResponse(message, aiMessageIndex) {
				try {
					// 这里替换为实际的API配置
					const apiUrl = 'https://mzyk.lrhdkj.cn/api/user.ai/aiChatStream/chat'
					const response = await fetch(apiUrl, {
						method: 'POST',
						//仅为示例，并非真实接口地址。
						body: JSON.stringify({
							message
						}),
						header: {
							'token': message, //自定义请求头信息
							'Content-Type': 'application/json',
							'Authorization': `Bearer YOUR_API_KEY` // 如果需要API密钥
						},
						timeout: 30000
					});

					// 处理流式响应
					await this.processStreamResponse(response, aiMessageIndex);
				} catch (error) {
					console.error('API Error:', error);
					// 更新AI消息为错误信息
					this.messages[aiMessageIndex].content = '抱歉，服务暂时不可用';
					this.messages[aiMessageIndex].htmlContent = marked.parse('抱歉，服务暂时不可用');
				}
			},

			async processStreamResponse(response, aiMessageIndex) {
				const reader = response.body.getReader();
				const decoder = new TextDecoder();
				let buffer = '';
				let accumulatedText = '';

				try {
					while (true) {
						const {
							done,
							value
						} = await reader.read();

						if (done) {
							break;
						}

						buffer += decoder.decode(value, {
							stream: true
						});
						const lines = buffer.split('\n');
						buffer = lines.pop(); // 保留最后一个可能不完整的行

						for (const line of lines) {
							if (line.trim() === '') continue;

							if (line.startsWith('data:')) {
								const jsonData = line.substring(5).trim();

								if (jsonData === '[DONE]') {
									continue;
								}

								try {
									const data = JSON.parse(jsonData);
									if (data.choices && data.choices[0].delta && data.choices[0].delta.content) {
										const content = data.choices[0].delta.content;
										accumulatedText += content;

										// 更新AI消息内容
										this.messages[aiMessageIndex].content = accumulatedText;

										// 智能解析Markdown
										if (this.shouldParseMarkdown(accumulatedText, content.slice(-1))) {
											this.messages[aiMessageIndex].htmlContent = marked.parse(accumulatedText);
										}

										this.$nextTick(() => {
											this.scrollToBottom();
										});
									}
								} catch (e) {
									console.error('JSON解析错误:', e);
								}
							}
						}
					}

					// 最终渲染完整的Markdown
					this.messages[aiMessageIndex].htmlContent = marked.parse(accumulatedText);
					this.messages[aiMessageIndex].isStreaming = false;

					this.$nextTick(() => {
						this.scrollToBottom();
					});
				} finally {
					reader.releaseLock();
				}
			},

			shouldParseMarkdown(currentText, newChar) {
				// 遇到这些可能开始或结束Markdown结构的字符时解析
				if (['\n', '*', '#', '>', '`', '-', '+', '1', '.', '!'].includes(newChar)) {
					return true;
				}

				// 遇到空格且前面有潜在的markdown标记时
				if (newChar === ' ' && currentText.length > 1) {
					const prevChar = currentText.charAt(currentText.length - 2);
					if (['*', '#', '>', '`', '-'].includes(prevChar)) {
						return true;
					}
				}

				// 每15个字符检查一次
				if (currentText.length % 15 === 0 && currentText.length > 0) {
					return true;
				}

				return false;
			},

			scrollToBottom() {
				const container = this.$refs.messagesContainer;
				if (container) {
					container.scrollTop = container.scrollHeight;
				}
			}
		}
	};
</script>

<style scoped>
	.chat-container {
		display: flex;
		flex-direction: column;
		height: 100vh;
	}

	.chat-header {
		padding: 16px;
		border-bottom: 1px solid #e0e0e0;
	}

	.messages-container {
		flex: 1;
		overflow-y: auto;
		padding: 16px;
	}

	.message {
		margin-bottom: 16px;
	}

	.message-content {
		padding: 12px 16px;
		border-radius: 8px;
	}

	.message.user .message-content {
		background-color: #e3f2fd;
		margin-left: 20%;
	}

	.message.ai .message-content {
		background-color: #f5f5f5;
		margin-right: 20%;
	}

	.message.system .message-content {
		background-color: #fff3e0;
	}

	.input-container {
		display: flex;
		padding: 16px;
		border-top: 1px solid #e0e0e0;
	}

	textarea {
		flex: 1;
		resize: none;
		padding: 12px;
		border: 1px solid #ccc;
		border-radius: 4px;
		font-family: inherit;
	}

	.send-button {
		margin-left: 10px;
		padding: 12px;
		background-color: #2196f3;
		color: white;
		border: none;
		border-radius: 4px;
		cursor: pointer;
	}

	.send-button:disabled {
		background-color: #bbdefb;
		cursor: not-allowed;
	}

	.loading-indicator {
		display: flex;
		padding: 12px 16px;
	}

	.loading-indicator span {
		width: 8px;
		height: 8px;
		background-color: #999;
		border-radius: 50%;
		margin: 0 4px;
		animation: blink 1.4s infinite;
	}

	.loading-indicator span:nth-child(2) {
		animation-delay: 0.2s;
	}

	.loading-indicator span:nth-child(3) {
		animation-delay: 0.4s;
	}

	@keyframes blink {

		0%,
		100% {
			opacity: 0.2;
		}

		50% {
			opacity: 1;
		}
	}

	.markdown-content {
		line-height: 1.6;
	}

	.markdown-content p {
		margin: 0 0 10px 0;
	}

	.markdown-content ul,
	.markdown-content ol {
		margin: 10px 0;
		padding-left: 20px;
	}

	.markdown-content li {
		margin-bottom: 5px;
	}

	.markdown-content strong {
		font-weight: bold;
	}

	.markdown-content em {
		font-style: italic;
	}

	.markdown-content code {
		background-color: #f4f4f4;
		padding: 2px 4px;
		border-radius: 3px;
		font-family: monospace;
	}

	.markdown-content pre {
		background-color: #f4f4f4;
		padding: 10px;
		border-radius: 5px;
		overflow-x: auto;
	}

	.markdown-content blockquote {
		border-left: 3px solid #ddd;
		margin: 10px 0;
		padding-left: 10px;
		color: #666;
	}
</style>